package com.ruoyi.demowechatpay.service;

import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest;
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.TransferService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import static com.github.wxpay.sdk.WXPayUtil.generateNonceStr;

@Slf4j
@Service
public class WxPayServiceV3 {

    @Autowired
    private WxPayService wxPayService;


    @Autowired
    private TransferService transferService;

    /**
     * JSAPI支付 - 正确的方法
     */
    public WxPayUnifiedOrderV3Result jsapiPay(String openid, String outTradeNo, BigDecimal amount, String description)
            throws WxPayException {
        WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();

        // 金额转换(元转分)
        int total = amount.multiply(new BigDecimal(100)).intValue();

        request.setAppid(wxPayService.getConfig().getAppId());
        request.setMchid(wxPayService.getConfig().getMchId());
        request.setDescription(description);
        request.setOutTradeNo(outTradeNo);
        request.setNotifyUrl(wxPayService.getConfig().getNotifyUrl() + "/payment");
        log.info("支付回调地址：{}", request.getNotifyUrl());
        // 设置金额
        WxPayUnifiedOrderV3Request.Amount amountObj = new WxPayUnifiedOrderV3Request.Amount();
        amountObj.setTotal(total);
        amountObj.setCurrency("CNY");
        request.setAmount(amountObj);

        // 设置支付者
        WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer();
        payer.setOpenid(openid);
        request.setPayer(payer);

        return wxPayService.unifiedOrderV3(TradeTypeEnum.JSAPI, request);
    }


    /**
     * JSAPI支付 - 正确的方法
     */
    public Map<String, String> packageJsapiPay(String openid, String outTradeNo, BigDecimal amount, String description)
            throws Exception {
        WxPayUnifiedOrderV3Result wxPayUnifiedOrderV3Result = jsapiPay(openid, outTradeNo, amount, description);
        if (wxPayUnifiedOrderV3Result != null && !StringUtils.isEmpty(wxPayUnifiedOrderV3Result.getPrepayId())) {
            return packagePrepayId(wxPayUnifiedOrderV3Result.getPrepayId());
        }else {
            throw new WxPayException("微信下单失败");
        }
    }


    /**
     * 退款 - 正确的方法
     */
    public WxPayRefundV3Result refund(String outTradeNo, String outRefundNo,
                                      BigDecimal totalAmount, BigDecimal refundAmount,
                                      String reason) throws WxPayException {
        WxPayRefundV3Request request = new WxPayRefundV3Request();

        // 金额转换
        int total = totalAmount.multiply(new BigDecimal(100)).intValue();
        int refund = refundAmount.multiply(new BigDecimal(100)).intValue();

        request.setOutTradeNo(outTradeNo);
        request.setOutRefundNo(outRefundNo);
        request.setNotifyUrl(wxPayService.getConfig().getNotifyUrl() + "/refund");
        request.setReason(reason);

        // 设置金额
        WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
        amount.setTotal(total);
        amount.setRefund(refund);
        amount.setCurrency("CNY");
        request.setAmount(amount);
        return wxPayService.refundV3(request);
    }


    /**
     * 发起转账到零钱
     *
     * @param openid 用户OpenID
     * @param amount 金额（元）
     * @param desc   转账描述
     */
    public TransferBatchesResult transferToBalance(String openid, BigDecimal amount, String desc)
            throws WxPayException {

        // 1. 构建请求对象
        TransferBatchesRequest request = TransferBatchesRequest.newBuilder()
                .appid(wxPayService.getConfig().getAppId())  // 公众号/小程序AppID
                .outBatchNo("BATCH" + System.currentTimeMillis()) // 批次号（需唯一）
                .batchName(desc)      // 批次名称
                .batchRemark(desc)    // 批次备注
                .totalAmount(amount.multiply(new BigDecimal(100)).intValue()) // 金额（分）
                .totalNum(1)          // 转账人数
                .transferDetailList(
                        Collections.singletonList(
                                TransferBatchesRequest.TransferDetail.newBuilder()
                                        .outDetailNo("DETAIL" + System.currentTimeMillis())
                                        .openid(openid)
                                        .transferAmount(amount.multiply(new BigDecimal(100)).intValue())
                                        .transferRemark(desc)
                                        .userName("用户实名姓名") // 可选（需与微信实名一致）
                                        .build()
                        )
                )
                .build();
        // 2. 发起转账
        return transferService.transferBatches(request);
    }

    /**
     * 查询支付订单 - 正确的方法
     */
    public WxPayOrderQueryV3Result queryOrder(String outTradeNo) throws WxPayException {
        return wxPayService.queryOrderV3(null, outTradeNo);
    }

    /**
     * 查询退款订单 - 正确的方法
     */
    public WxPayRefundQueryV3Result queryRefund(String outRefundNo) throws WxPayException {
        return wxPayService.refundQueryV3(outRefundNo);
    }

    /**
     * 关闭订单 - 正确的方法
     */
    public void closeOrder(String outTradeNo) throws WxPayException {
        wxPayService.closeOrderV3(outTradeNo);
    }


    public  Map<String, String> packagePrepayId(String prepayId) throws Exception {
        // 时间戳
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
// 随机字符串
        String nonceStr = generateNonceStr();
// package 固定格式
        String packageStr = "prepay_id=" + prepayId;

// 构造签名串（V3 使用 RSA 签名）
        String signStr = wxPayService.getConfig().getAppId() + "\n" +
                timestamp + "\n" +
                nonceStr + "\n" +
                packageStr + "\n";

// 使用商户私钥签名
        String paySign = signV3(signStr); // WxJava 可能未直接提供 signV3，需手动实现

// 返回给前端的参数
        Map<String, String> payParams = new HashMap<>();
        payParams.put("appId", wxPayService.getConfig().getAppId());
        payParams.put("timeStamp", timestamp);
        payParams.put("nonceStr", nonceStr);
        payParams.put("package", packageStr);
        payParams.put("signType", "RSA");
        payParams.put("paySign", paySign);

        return payParams;
    }

    public String signV3(String message) throws Exception {
        PrivateKey key  = wxPayService.getConfig().getPrivateKey(); // 商户私钥

        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(key);
        signature.update(message.getBytes(StandardCharsets.UTF_8));

        return Base64.getEncoder().encodeToString(signature.sign());
    }
}
